﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;

using Please_starve.Common.Managers;

namespace Please_starve.Sprites
{
    public class SpriteData
    {
        public Sprite3D Sprite;
        public Vector3 Position;
        public Matrix Matrix;
        public VertexBuffer VertexBuffer;
        float scale;

        float fps;
        double elapsed;
        int currentRow;
        int currentColoumn;

        bool faceCamera;

        public SpriteData(Sprite3D sprite, float scale, Vector3 position)
        {
            this.fps = 0;
            this.initialize(sprite, scale, position);
        }

        public SpriteData(Sprite3D sprite, float scale, Vector3 position, float fps, bool faceCamera = false)
        {
            this.faceCamera = faceCamera;
            this.fps = 1f / fps;
            this.initialize(sprite, scale, position);
        }

        private void initialize(Sprite3D sprite, float scale, Vector3 position)
        {
            this.Sprite = sprite;
            this.scale = scale;
            this.Position = position;
            this.Matrix = Matrix.CreateScale(scale) * Matrix.CreateTranslation(position);

            VertexPositionNormalTexture[] verts = sprite.UpdateVertex(sprite.Sprite3DTextureInfo.framePositions[0][0]);
            this.VertexBuffer = new DynamicVertexBuffer(GameServices.GetService<GraphicsDevice>(), typeof(VertexPositionNormalTexture), verts.Length, BufferUsage.None);
            this.VertexBuffer.SetData<VertexPositionNormalTexture>(verts);
        }

        public void Update(GameTime gameTime)
        {
            if (faceCamera)
            {
                float angle = Cameras.Camera.CurrentZoom.Y / Cameras.Camera.CurrentZoom.Z;
                this.Matrix = Matrix.CreateScale(scale) * Matrix.CreateRotationX(-angle) * Matrix.CreateTranslation(Position);
            }

            if (this.fps > 0)
            {
                updateFrame(gameTime);
            }
        }

        private void updateFrame(GameTime gameTime)
        {
            this.elapsed += gameTime.ElapsedGameTime.TotalSeconds;

            if (this.elapsed > this.fps)
                this.elapsed = 0;
            else
                return;

            if (++currentColoumn == Sprite.Sprite3DTextureInfo.coloumns)
            {
                currentColoumn = 0;
                currentRow++;
            }
            if (currentRow == Sprite.Sprite3DTextureInfo.rows)
            {
                currentRow = 0;
            }

            Vector2[] texturePosition = Sprite.Sprite3DTextureInfo.framePositions[currentRow][currentColoumn];
            VertexPositionNormalTexture[] verts = Sprite.UpdateVertex(texturePosition);
            VertexBuffer.SetData<VertexPositionNormalTexture>(verts);
        }

        public void Draw(GraphicsDevice graphicsDevice, BasicEffect basicEffect)
        {
            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                graphicsDevice.SetVertexBuffer(VertexBuffer);
                basicEffect.World = Matrix;
                basicEffect.Texture = Sprite.Texture;
                basicEffect.CurrentTechnique.Passes[0].Apply();
                graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
            }
        }
    }
}
